package com.zone.sdk.common.http;

import com.google.gson.Gson;
import com.zone.sdk.common.http.apimock.ApiMock;
import com.zone.sdk.common.http.apimock.interceptor.MockInterceptor;

import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

public class OkHttpManager {

    protected static final int CONNECT_TIME_OUT = 15000;
    protected static final int WRITE_TIME_OUT = 15000;
    protected static final int READ_TIME_OUT = 15000;

    protected OkHttpClient mOkHttpClient;

    protected Retrofit mRetrofit;

    protected static OkHttpManager instance;

    protected static Header header;

    protected static HeaderInterceptor headerInterceptor;

    protected static BodyInterceptor bodyInterceptor;

    protected static String baseUrl;

    public void init(String baseUrl) {
        OkHttpManager.baseUrl = baseUrl;
    }

    protected OkHttpManager(){
    }

    public synchronized static OkHttpManager getInstance() {
        if (instance == null){
            instance = new OkHttpManager();
        }
        return instance;
    }

    public void initAccount(String authorization){
        if (header == null){
            header = new Header();
        }
        header.setAuthorization_account(authorization);
    }

    public void initApp(String authorization){
        if (header == null){
            header = new Header();
        }
        header.setAuthorization_account(authorization);
    }



    public <T> T build(final Class<T> service){

        OkHttpClient.Builder builder = new OkHttpClient().newBuilder()
                .connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS)
                .readTimeout(READ_TIME_OUT, TimeUnit.SECONDS)
                .writeTimeout(WRITE_TIME_OUT, TimeUnit.SECONDS);
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        if (ApiMock.isMock()){
            builder.addInterceptor(new MockInterceptor());
        }else {
            builder.addInterceptor(loggingInterceptor);
//        HeaderInterceptor headerInterceptor = new HeaderInterceptor();
            builder.addInterceptor(headerInterceptor);
            builder.addInterceptor(bodyInterceptor);
        }

        mOkHttpClient = builder.build();

        mRetrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(mOkHttpClient)

                .build();
        return mRetrofit.create(service);
    }

    public static class HeaderInterceptor implements Interceptor {

        private static Map<String, String> paramsMap = new HashMap<>();

        public Map<String, String> getParamsMap() {
            return paramsMap;
        }

        public void addParam(String key, String value){
            paramsMap.put(key, value);
        }

        @NotNull
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            Request.Builder requestBuilder = request.newBuilder();
            Headers.Builder headerBuilder = request.headers().newBuilder();
            if (paramsMap.size() > 0){
                Iterator<String> iterator = paramsMap.keySet().iterator();
                while (iterator.hasNext()){
                    String key = iterator.next();
                    headerBuilder.add(key, Objects.requireNonNull(paramsMap.get(key)));
                }
            }
            String timestamp = String.valueOf(System.currentTimeMillis());
//            headerBuilder.add("Authorization", "Bearer"+token);
            headerBuilder.add("timestamp", timestamp);
            headerBuilder.add("nonce", timestamp);
            headerBuilder.add("requestId", timestamp);
            requestBuilder.headers(headerBuilder.build());
            return chain.proceed(request);
        }
    }

    public static class BodyInterceptor implements Interceptor {

        private static Map<String, String> paramsMap = new HashMap<>();

        public Map<String, String> getParamsMap() {
            return paramsMap;
        }

        public void addParam(String key, String value){
            paramsMap.put(key, value);
        }

        @NotNull
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            Request.Builder builder = request.newBuilder();
            if (request.method().equals("POST")
                    && ( Objects.requireNonNull(Objects.requireNonNull(request.body()).contentType()).subtype().equals("x-www-form-urlencoded")
                        || Objects.requireNonNull(Objects.requireNonNull(request.body()).contentType()).subtype().equals("application/json;charset=utf-8"))
            ){
                if (request.body() instanceof FormBody) {
                    FormBody.Builder bodyBuilder = new FormBody.Builder();
                    FormBody formBody = (FormBody) request.body();
                    //把原来的参数添加到新的构造器，（因为没找到直接添加，所以就new新的）
                    for (int i = 0; i < formBody.size(); i++) {
                        bodyBuilder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i));
                    }
//                    FormBody.Builder builder = new FormBody.Builder();
                    if (paramsMap.size() > 0){
                        for (String key : paramsMap.keySet()) {
                            bodyBuilder.add(key, Objects.requireNonNull(paramsMap.get(key)));
                        }
                    }
                    formBody = bodyBuilder.build();
                    request = builder.post(formBody).build();
                }else if (request.body() instanceof PostJsonBody) {
                    RequestBody requestBody = request.body();
                    String content = ((PostJsonBody) requestBody).getContent();
                    HashMap hashMap = new Gson().fromJson(content, HashMap.class);
                    builder.post(PostJsonBody.create(new Gson().toJson(hashMap)));
                }else if (request.body() instanceof MultipartBody){

                }
            }
            return chain.proceed(request);
        }
    }


    public OkHttpClient getmOkHttpClient() {
        return mOkHttpClient;
    }

    public Retrofit getmRetrofit() {
        return mRetrofit;
    }

    public static class Header {
        /********账号*********/
        private String authorization_account;
        /*********超级APP********/
        private String token;
        /*********商城 & 评论********/
        private String x_device_from;
        private String authorization_appstore;
        private String timestamp;
        private String nonce;
        private String sign;
        private String request_id;

        public String getAuthorization_account() {
            return authorization_account;
        }

        public void setAuthorization_account(String authorization_account) {
            this.authorization_account = authorization_account;
        }

        public String getToken() {
            return token;
        }

        public void setToken(String token) {
            this.token = token;
        }

        public String getX_device_from() {
            return x_device_from;
        }

        public void setX_device_from(String x_device_from) {
            this.x_device_from = x_device_from;
        }

        public String getAuthorization_appstore() {
            return authorization_appstore;
        }

        public void setAuthorization_appstore(String authorization_appstore) {
            this.authorization_appstore = authorization_appstore;
        }

        public String getTimestamp() {
            return timestamp;
        }

        public void setTimestamp(String timestamp) {
            this.timestamp = timestamp;
        }

        public String getNonce() {
            return nonce;
        }

        public void setNonce(String nonce) {
            this.nonce = nonce;
        }

        public String getSign() {
            return sign;
        }

        public void setSign(String sign) {
            this.sign = sign;
        }

        public String getRequest_id() {
            return request_id;
        }

        public void setRequest_id(String request_id) {
            this.request_id = request_id;
        }
    }


}
